{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Berechnungen mit Höhendifferenzen"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Neben der Berechnung unter Einbeziehung von Höhendifferenzen wird auch gezeigt, wie man ein Netzwerk plotten kann.\n",
    "\n",
    "<img src=\"pics/rng_height.png\">\n",
    "\n",
    "Die pandapipes-Umgebung basiert auf der Python-Bibliothek \"pandas\". Ein Netzwerk enthält Tabellen für jeden Komponententyp, der eingesetzt wird. Die Zeilen der Tabellen entsprechen den tatsächlich im Netzwerk vorhandenen Komponenten. Jede Zeile in einer Komponententabelle repräsentiert also eine Komponente des jeweiligen Typs. Die Spalten entsprechen den Eigenschaften des Komponententyps.\n",
    "\n",
    "Durch das Ausführen der folgenden Code-Zellen des Notebooks werden die für das betrachtete Netz benötigten Komponententabellen erstellt. Wenn Sie weitere Informationen zu den einzelnen Parametern der Komponenten benötigen, so finden Sie diese in der pandapipes-Dokumentation unter Punkt \"Datastructure and Components\".\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Leeres Netzwerk"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Zunächst wird pandapipes importiert. Danach wird ein leeres Netzwerk mit der Angabe des zu verwendenden Fluids hinzugefügt. Wir greifen auf die in pandapipes vorhandene Bibliothek zu und wählen Wasser als Fluid:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import pandapipes as pp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net = pp.create_empty_network(fluid=\"water\") # create an empty network"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die <span style=\"color:blue\">create</span>-Funktionen werden nun eingesetzt, um neue Komponenten zu erzeugen. Diese werden automatisch den entsprechenden Tabellen hinzugefügt. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Junctions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "junction1 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 352, name=\"Junction 1\")\n",
    "junction2 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 358, name=\"Junction 2\")\n",
    "junction3 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 361, name=\"Junction 3\")\n",
    "junction4 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 346, name=\"Junction 4\")\n",
    "junction5 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 400, name=\"Junction 5\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die junctions befinden sich jetzt im Netz-Container und können abgerufen werden. Einigen Parametern, die beim Funktionsaufruf nicht explizit erwähnt worden sind, wurden Standardwerte zugewiesen. Beachten Sie: Im Vergleich zum Einführungstutorial wurde den Junctions eine Höheninformation hinzugefügt. Die durch Höhenunterschiede vorhandene potentielle Energie wird bei der Hydraulikberechnung berücksichtigt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.junction # show junction table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Im nächsten Schritt werden dem Netz weitere Komponenten hinzugefügt, angefangen beim External Grid:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### External Grid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "In unserem Beispiel wird das External Grid mit der Junction-Variable junction5 verbunden. Der Druck beträgt 0.5 bar. In der späteren Auswertung wird der Druck, den Sie an junction5 abrufen, folglich ebenfalls 0.5 bar betragen.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "medium_pressure_grid = pp.create_ext_grid(net, junction=junction5, p_bar=0.5, t_k=293.15, name=\"Grid Connection\")\n",
    "\n",
    "net.ext_grid # show external grid table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Rohre"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Das Netzwerk enthält 4 Rohre, die zwischen je zwei Knoten verlaufen. Die Verbindungspunkte und die jeweiligen Rohrlängen sind im Diagramm zu sehen. Die Parameter sind weitgehend bereits bekannt. Beachten Sie aber, dass Rohr 4 eine andere Rauigkeit `k_mm` zugewiesen bekommt. Der Standardwert beträgt 1 mm.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pipe1 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=0.545, diameter_m=0.2,  name=\"Pipe 1\")\n",
    "pipe2 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=0.095, diameter_m=0.15, name=\"Pipe 2\")\n",
    "pipe3 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction4, length_km=0.285, diameter_m=0.15, name=\"Pipe 3\")\n",
    "pipe4 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction5, length_km=0.43, diameter_m=0.15, k_mm=0.5, name=\"Pipe 4\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Damit sieht die Tabelle der Rohrkomponenten wie folgt aus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.pipe # show pipe table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die Parameter from_junction und to_junction geben die Orientierung des Rohrs an. Wenn die Flussrichtung tatsächlich aus Richtung from_junction in Richtung to_junction verläuft, ist das Vorzeichen der berechneten Strömungsgeschwindigkeit positiv. Andernfalls nimmt die Strömungsgeschwindigkeit negative Werte an."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Senken\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mit Hilfe einer Senke kann eine konstante Abnahme definiert werden. An dieser Stelle werden zwei\n",
    "sink-Komponente mit einem Massestrom in Höhe von 277 g/s bzw. 139 g/s definiert. Senken und Quellen\n",
    "werden immer einer bestimmten Junction zugeordnet. Das Vorzeichen des Massestroms ist positiv,\n",
    "wenn ein Massestrom aus dem System entnommen wird.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sink = pp.create_sink(net, junction=junction4, mdot_kg_per_s=0.277, name=\"Sink 1\")\n",
    "sink = pp.create_sink(net, junction=junction3, mdot_kg_per_s=0.139, name=\"Sink 2\")\n",
    "net.sink"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Wir starten jetzt die Berechnung. Wahrscheinlich ist Ihnen bekannt, dass es mehrere Modelle gibt, um den Reibungseinfluss der Rohrleitungen zu berücksichtigen. Standardmäßig wird das Modell nach Nikuradse verwendet. Eine klare Trennung zwischen laminarer und turbulenter Rohrströmung ist in pandapipes nicht implementiert. Übliche Programme bieten sonst die Möglichkeit, zwischen voll ausgebildeter, laminarer Rohrströmung und turbulenter Strömung zu unterscheiden. Laminare Strömungen sind in den üblichen pandapipes-Anwendungen nicht zu erwarten.\n",
    "\n",
    "Dennoch ist geplant, eine entsprechende Unterscheidung in Zukunft zu implementieren. Im Pipeflow-Befehl wird an dieser Stelle explizit der Parameter für das Nikuradse-Modell gesetzt, obwohl dies die Standardeinstellung ist. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "pp.pipeflow(net, friction_model =\"nikuradse\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Nun lassen wir uns die Ergebnisse anzeigen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "net.res_junction # calculated pressure and temperature at junctions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "net.res_pipe  # velocities, mass flows through pipes and other results\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Plotting\n",
    "\n",
    "Mit Hilfe des Python-Moduls matplotlib lassen sich die Netze auch mit wenig Aufwand direkt plotten."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "from pandapipes.plotting.simple_plot import simple_plot as sp\n",
    "\n",
    "sp(net, plot_sinks = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Koordinaten werden den junctions automatisch zugewiesen, solange diese nicht explizit zugewiesen werden."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}